/* Copyright (C) 2011 clueless <clueless.mmopeon@gmail.com>
 *
 * This file is part of MMO Peon.
 *
 * MMO Peon is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * MMO Peon is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MMO Peon.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "packets.h"
#include "log.h"
#include "classes/objectmap.h"
#include <sstream>
#include <iomanip>

void ParseSpawnObjectPacket(struct PktSpawnObject *packet);
void ParseDespawnObjectPacket(struct PktDespawnObject *packet);
void ParseMoveObject1Packet(struct PktMoveObject1 * packet);
void ParseMoveObject2Packet(struct PktMoveObject2 * packet);
void ParseMoveObject3Packet(struct PktMoveObject3 * packet);

SendFunction SendPacket = (SendFunction)0x005FEC30;

void ParseRecvPacket(struct PktWrapper *packet)
{
    switch(packet->content.contentId)
    {
        case 0x14:
            ParseSpawnObjectPacket((struct PktSpawnObject *)packet->content.data);
            break;
        case 0x15:
            ParseDespawnObjectPacket((struct PktDespawnObject *)packet->content.data);
            break;
        case 0x17:
            ParseMoveObject1Packet((struct PktMoveObject1 *)packet->content.data);
            break;
        case 0x4C:
            ParseMoveObject2Packet((struct PktMoveObject2 *)packet->content.data);
            break;
        case 0x23:
            ParseMoveObject3Packet((struct PktMoveObject3 *)packet->content.data);
            break;
        default:
            break;
    }
}

void ParseSendPacket(struct PktWrapper *packet)
{

}

void ParseDespawnObjectPacket(struct PktDespawnObject *packet)
{
    ObjectMap objectMap(true);

    if (!objectMap.HasObject(packet->objectId))
    {
        std::ostringstream out;
        out << "Received despawn packet for object " << std::hex << packet->objectId
            << " but that ID is not available in the map";
        LogWrite(LOG_NORMAL, out.str());
        return;
    }

    std::ostringstream out;
    out << "DESPAWN   " << packet->objectId;
    LogWrite(LOG_NORMAL, out.str());

    objectMap.Delete(packet->objectId);
}

void ParseSpawnObjectPacket(struct PktSpawnObject *packet)
{
    ObjectMap objectMap(true);

    if (objectMap.HasObject(packet->objectId))
    {
        std::ostringstream out;
        out << "Received spawn packet for object " << std::hex << packet->objectId
            << " but that ID is already in the map";
        LogWrite(LOG_NORMAL, out.str());
        return;
    }

    GameObject object;
    if ((packet->objectType | 0x3EB) == 0x3EB)
        object.name = packet->name;
    else
        object.name = "<noname>";

    object.objectId     = packet->objectId;
    object.objectId2    = packet->objectId2;
    object.objectType   = packet->objectType;
    object.coords       = packet->coords;

    std::ostringstream out;
    out << "SPAWN     "
        << object.objectId  << " "
        << object.objectId2 << " "
        << object.objectType << " "
        << " X: " << object.coords.x
        << " Y: " << object.coords.y
        << " Z: " << object.coords.z
        << " " << object.name;
    LogWrite(LOG_NORMAL, out.str());

    objectMap.Add(object);
}

void MoveObjectUniversal(uint32_t objectId, RomCoords newCoords)
{
    ObjectMap objectMap(true);

    if (objectMap.HasObject(objectId) == false)
    {
        std::ostringstream out;
        out << "Received move packet for object " << std::hex << objectId
            << " but that ID is not in the map";
        //LogWrite(LOG_NORMAL, out.str());
        return;
    }

    GameObject *object = objectMap.Get(objectId);
    object->coords = newCoords;

    std::ostringstream out;
    out << "MOVE      "
        << object->objectId  << " "
        << object->objectId2 << " "
        << object->objectType << " "
        << " X: " << object->coords.x
        << " Y: " << object->coords.y
        << " Z: " << object->coords.z
        << " " << object->name;

    LogWrite(LOG_NORMAL, out.str());
}

void ParseMoveObject1Packet(struct PktMoveObject1 * packet)
{
    MoveObjectUniversal(packet->objectId, packet->newCoords);
}

void ParseMoveObject2Packet(struct PktMoveObject2 * packet)
{
    MoveObjectUniversal(packet->objectId, packet->newCoords);
}

void ParseMoveObject3Packet(struct PktMoveObject3 * packet)
{
    MoveObjectUniversal(packet->objectId, packet->newCoords);
}
